"""
深度学习训练配置管理器 - 基于单例模式的全局配置类

核心功能：
1. 集中管理训练过程所有超参数
2. 支持动态参数修改与验证
3. 提供配置状态保存与展示
4. 集成Visdom可视化设置

设计模式：
- 单例模式：通过类变量实现全局唯一配置[2,3](@ref)
- 策略模式：可切换优化器等算法组件[5](@ref)
"""

import os
from datetime import datetime
from pprint import pprint
import setproctitle  # 进程命名工具


class Config:
    """训练配置主类（隐式单例）"""

    # ========== 基础配置 ==========
    date = datetime.now().strftime('%Y%m%d')
    name = 'DuSp3_LK'+str(date)  # 实验标识名（用于保存路径和进程命名）
    gpu_id = '0'  # 使用GPU编号（需与train.py中实际GPU数量对应）
    setproctitle.setproctitle("%s" % name)  # 设置进程名便于监控

    # ========== 数据路径配置 ==========
    # train_data_path = 'tools/XJU4_get_txt/txt/20250510train.txt'  # 训练集路径
    train_data_path = 'tools/XJU4_get_txt/txt/20250522train.txt'
    # test_data_path = 'tools/XJU4_get_txt/txt/20250510val.txt'  # 验证集路径
    test_data_path = 'tools/XJU4_get_txt/txt/20250522val.txt'
    checkpoint_path = 'checkpoints'  # 检查点根目录
    log_path = 'log'  # 日志目录
    saver_path = os.path.join(checkpoint_path, name)  # 实验专属保存路径

    max_save = 200 # 最大检查点保存数量

    # ========== Visdom可视化配置 ==========
    vis_env = 'python'  # Visdom环境名
    port = 8097  # Visdom服务端口
    vis_train_loss_every = 40  # 损失可视化间隔（步数）
    vis_train_acc_every = 40  # 准确率可视化间隔
    vis_train_img_every = 120  # 图像可视化间隔
    val_every = 200  # 验证间隔
    vis_save_path = '../log/visdom' # Visdom保存路径

    # ========== 训练超参数 ==========
    epoch = 10  # 总训练轮次
    pretrained_model = ''  # 预训练模型路径
    weight_decay = 0.00001  # L2正则化系数
    lr_decay = 0.1  # 学习率衰减系数
    lr = 1e-3  # 初始学习率
    momentum = 0.9  # SGD动量参数
    use_adam = True  # 使用Adam优化器（False时使用SGD）
    train_batch_size = 8  # 训练批大小
    val_batch_size = 4  # 验证批大小
    test_batch_size = 4  # 测试批大小

    # ========== 评估参数 ==========
    acc_sigmoid_th = 0.5  # 分类阈值（二值化分割）
    pos_pixel_weight = 8  # 正样本（裂缝像素）权重（用于类别不平衡）

    # ========== 检查点策略 ==========
    save_format = ''  # 保存文件名格式
    save_acc = -1  # 最佳准确率记录
    save_pos_acc = -1  # 最佳正样本准确率记录

    # ========== Transformer架构参数 ==========
    hidden_size = 768  # 编码器隐藏层维度
    grid_size = 16  # 特征网格大小
    patchsize = 1  # 图像分块大小
    image_size = 256  # 输入图像尺寸
    num_layers = 6  # Transformer编码器层数
    mlp_dim = 3072  # MLP扩展维度
    dropout_rate = 0.1  # 随机失活率
    num_heads = 12  # 注意力头数
    attention_dropout_rate = 0.0  # 注意力机制失活率

    def _parse(self, kwargs):
        """动态参数更新方法

        参数：
            kwargs: 参数字典（如从命令行传入）

        流程：
            1. 验证参数合法性
            2. 更新类属性
            3. 打印当前配置
        """
        state_dict = self._state_dict()
        for k, v in kwargs.items():
            if k not in state_dict:
                raise ValueError('UnKnown Option: "--%s"' % k)
            setattr(self, k, v)

        print('======user config========')
        pprint(self._state_dict())
        print('==========end============')

    def _state_dict(self):
        """生成配置状态字典

        返回：
            dict: 所有非私有属性的键值对
        """
        return {k: getattr(self, k) for k, _ in Config.__dict__.items() \
                if not k.startswith('_')}

    def show(self):
        """打印当前配置"""
        print('======user config========')
        pprint(self._state_dict())
        print('==========end============')